/*
    Copyright (C) 2021 Huawei Device Co., Ltd.
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

package com.danikula.videocache;

import com.danikula.videocache.bean.ProgressBean;
import com.danikula.videocache.util.DisplayUtils;
import com.danikula.videocache.util.ElementUtil;
import com.example.mylibrary.ResourceTable;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 分段显示进度条
 */
public class ProgressbarView extends Component implements Component.DrawTask {
    private final int DEFAULT_WIDTH = 450;
    private final int DEFAULT_HEIGTH = 40;
    private final String DEFAULT_SHAPE_NAME = "square";
    private final int DEFAULT_SHAPE = 0;
    private final int DEFAULT_MAX = 100;
    private final int DEFAULT_PROGRESS = 0;
    private final Color DEFAULT_PROGRESS_COLOR = new Color(ResourceTable.Color_p_76B034);
    private final Color DEFAULT_PROGRESS_BACK_COLOR = new Color(ResourceTable.Color_p_EFEFEF);
    private final int DEFAULT_CIRCLE_R = 50;
    private final int DEFAULT_SQUARE_R = 20;
    private final int DEFAULT_TEXT_SIZE = 30;
    private int progress = DEFAULT_PROGRESS;
    private int max = DEFAULT_MAX;
    private float mWidth = DEFAULT_WIDTH;
    private float mHeight = DEFAULT_HEIGTH;
    private int mShapeType = DEFAULT_SHAPE;
    private String mShapeTypeName = DEFAULT_SHAPE_NAME;
    private Color proColor = DEFAULT_PROGRESS_COLOR;
    private Color proBackColor = DEFAULT_PROGRESS_BACK_COLOR;
    private Color textLowColor = Color.BLACK;
    private Color textMiddleColor = Color.BLUE;
    private Color textHighColor = Color.RED;
    private Color progressSegmentColor = proColor;
    private Color progressDoubleSegColor = Color.GRAY;
    private float squareRadius = DEFAULT_SQUARE_R;
    private float textSize = DEFAULT_TEXT_SIZE;
    private boolean showText;
    private float circleX = DEFAULT_CIRCLE_R + 20;
    private float circleR = DEFAULT_CIRCLE_R;
    private float startX;
    private float translateX;
    private float startY;
    private float translateY;
    private float startR = -90;
    private Paint paint;
    private RectFloat circleRectf;
    private RectFloat squareRectf;
    private List<ProgressBean> progressList;

    public ProgressbarView(Context context) {
        this(context, null);
    }

    public ProgressbarView(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public ProgressbarView(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initProgressData();
        if (context != null && attrs != null) {
            initView(context, attrs, defStyleAttr);
        }
    }

    private void initProgressData() {
        progressList = new ArrayList<>();
        for (int i = 0; i < 101; i++) {
            ProgressBean bean = new ProgressBean();
            bean.setDefault(true);
            bean.setProgress(i);
            progressList.add(bean);
        }
    }

    /**
     * 初始化分段进度条的各种参数
     *
     * @param context 上下文
     */
    public void initWidget(Context context) {
        mWidth = DisplayUtils.vp2px(context, mWidth);
        mHeight = DisplayUtils.vp2px(context, mHeight);
        circleR = DisplayUtils.vp2px(context, circleR);
        circleX = DisplayUtils.vp2px(context, circleX);
        textSize = DisplayUtils.fp2px(context, textSize);
        squareRadius = DisplayUtils.vp2px(context, squareRadius);
        paint = new Paint();
        circleRectf = new RectFloat();
        squareRectf = new RectFloat();
        initShapeType(context, null);
        paint.setAntiAlias(true);
        paint.setAntiAlias(true);
        paint.setColor(new Color(ElementUtil.getColor(context, ResourceTable.Color_p_EFEFEF)));
        paint.setStrokeWidth(10);
        paint.setStyle(Paint.Style.FILL_STYLE);
        addDrawTask(this::onDraw);
    }


    public void setmWidth(float mWidth) {
        this.mWidth = mWidth;
    }

    public void setmHeight(float mHeight) {
        this.mHeight = mHeight;
    }

    public void setProColor(Color proColor) {
        this.proColor = proColor;
    }

    public void setProBackColor(Color proBackColor) {
        this.proBackColor = proBackColor;
    }

    public void setTextLowColor(Color textLowColor) {
        this.textLowColor = textLowColor;
    }

    public void setTextMiddleColor(Color textMiddleColor) {
        this.textMiddleColor = textMiddleColor;
    }

    public void setTextHighColor(Color textHighColor) {
        this.textHighColor = textHighColor;
    }

    public void setProgressSegmentColor(Color progressSegmentColor) {
        this.progressSegmentColor = progressSegmentColor;
    }

    public void setProgressDoubleSegColor(Color progressDoubleSegColor) {
        this.progressDoubleSegColor = progressDoubleSegColor;
    }

    public void setSquareRadius(float squareRadius) {
        this.squareRadius = squareRadius;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    public void setShowText(boolean showText) {
        this.showText = showText;
    }

    public void setCircleX(float circleX) {
        this.circleX = circleX;
    }

    public void setCircleR(float circleR) {
        this.circleR = circleR;
    }

    public void setStartX(float startX) {
        this.startX = startX;
    }

    public void setStartY(float startY) {
        this.startY = startY;
    }

    public void setStartR(float startR) {
        this.startR = startR;
    }

    public void setmShapeTypeName(String mShapeTypeName) {
        this.mShapeTypeName = mShapeTypeName;
    }

    private void initView(Context context, AttrSet attrs, int defStyleAttr) {
        final int density = context.getResourceManager().getDeviceCapability().screenDensity / 160;
        mWidth = attrs.getAttr(DiyProgressValue.P_WIDTH).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_WIDTH).get().getDimensionValue() * density : DEFAULT_WIDTH * density;
        mHeight = attrs.getAttr(DiyProgressValue.P_HEIGHT).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_HEIGHT).get().getDimensionValue() * density : DEFAULT_HEIGTH * density;
        initShapeType(context, attrs);
        showText = attrs.getAttr(DiyProgressValue.P_SHOW_TEXT).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_SHOW_TEXT).get().getBoolValue() : false;
        if (mShapeType == 1) {
            circleR = attrs.getAttr(DiyProgressValue.P_CIRCLE_RADIUS).isPresent() ?
                    attrs.getAttr(DiyProgressValue.P_CIRCLE_RADIUS).get().getDimensionValue() * density :
                    DEFAULT_CIRCLE_R * density;
            circleX = attrs.getAttr(DiyProgressValue.P_CIRCLE_X_Y).isPresent() ?
                    attrs.getAttr(DiyProgressValue.P_CIRCLE_X_Y).get().getDimensionValue() * density :
                    (circleR + 20) * density;
        }
        if (mShapeType == 2) {
            squareRadius = attrs.getAttr(DiyProgressValue.P_SQUARE_RADIUS).isPresent() ?
                    attrs.getAttr(DiyProgressValue.P_SQUARE_RADIUS).get().getDimensionValue() * density :
                    DEFAULT_SQUARE_R * density;
        }

        if (showText) {
            textSize = attrs.getAttr(DiyProgressValue.P_TEXT_SIZE).isPresent() ?
                    attrs.getAttr(DiyProgressValue.P_TEXT_SIZE).get().getDimensionValue() * density :
                    DEFAULT_TEXT_SIZE * density;
        }
        max = attrs.getAttr(DiyProgressValue.P_MAX_VALUE).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_MAX_VALUE).get().getIntegerValue() : DEFAULT_MAX;

        progress = attrs.getAttr(DiyProgressValue.P_PROGRESS_VALUE).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_PROGRESS_VALUE).get().getIntegerValue() : DEFAULT_PROGRESS;

        proColor = attrs.getAttr(DiyProgressValue.P_PROGRESS_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_PROGRESS_COLOR).get().getColorValue() : DEFAULT_PROGRESS_COLOR;

        proBackColor = attrs.getAttr(DiyProgressValue.P_PROGRESS_BACK_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_PROGRESS_BACK_COLOR).get().getColorValue() :
                DEFAULT_PROGRESS_BACK_COLOR;

        textLowColor = attrs.getAttr(DiyProgressValue.P_TEXT_LOW_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_TEXT_LOW_COLOR).get().getColorValue() : Color.BLACK;

        textMiddleColor = attrs.getAttr(DiyProgressValue.P_TEXT_MIDDLE_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_TEXT_MIDDLE_COLOR).get().getColorValue() : Color.BLUE;

        textHighColor = attrs.getAttr(DiyProgressValue.P_TEXT_HIGH_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_TEXT_HIGH_COLOR).get().getColorValue() : Color.RED;

        progressSegmentColor = attrs.getAttr(DiyProgressValue.P_PROGRESS_SEMENT_COLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_PROGRESS_SEMENT_COLOR).get().getColorValue() : DEFAULT_PROGRESS_COLOR;

        progressDoubleSegColor = attrs.getAttr(DiyProgressValue.P_PROGRESS_DOUBLE_SEGCOLOR).isPresent() ?
                attrs.getAttr(DiyProgressValue.P_PROGRESS_DOUBLE_SEGCOLOR).get().getColorValue() : Color.GRAY;
        initPait(context);
        addDrawTask(this);
    }

    private void initPait(Context context) {
        paint = new Paint();
        circleRectf = new RectFloat();
        squareRectf = new RectFloat();
        progressList = new ArrayList<>();
        paint.setAntiAlias(true);
        paint.setAntiAlias(true);
        paint.setColor(new Color(ElementUtil.getColor(context, ResourceTable.Color_p_EFEFEF)));
        paint.setStrokeWidth(10);
        paint.setStyle(Paint.Style.FILL_STYLE);
    }

    private void initShapeType(Context context, AttrSet attrs) {
        try {
            if (attrs != null) {
                mShapeTypeName = attrs.getAttr(DiyProgressValue.P_SHAPE_TYPE).isPresent() ?
                        attrs.getAttr(DiyProgressValue.P_SHAPE_TYPE).get().getStringValue() : DEFAULT_SHAPE_NAME;
            }
            switch (mShapeTypeName) {
                case DiyProgressValue.P_SHAPE_TYPE_RECTANGLE:
                    mShapeType = context.getResourceManager().getElement(ResourceTable.Integer_rectangle).getInteger();
                    break;
                case DiyProgressValue.P_SHAPE_TYPE_CIRCLE:
                    mShapeType = context.getResourceManager().getElement(ResourceTable.Integer_circle).getInteger();
                    break;
                case DiyProgressValue.P_SHAPE_TYPE_SQUARE:
                    mShapeType = context.getResourceManager().getElement(ResourceTable.Integer_square).getInteger();
                    break;
                default:
                    mShapeType = context.getResourceManager().getElement(ResourceTable.Integer_square).getInteger();
                    break;
            }

        } catch (IOException | NotExistException | WrongTypeException e) {
            mShapeType = DEFAULT_SHAPE;
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        paint.setColor(proBackColor);
        paint.setStrokeWidth(10);
        paint.setTextSize((int) textSize);
        // 方便将进度条居中
        if (translateX == 0) {
            int estimatedWidth = getEstimatedWidth();
            translateX = (estimatedWidth - mWidth) / 2;
        }
        if (translateY == 0) {
            int estimatedHeight = getEstimatedHeight();
            translateY = (estimatedHeight - mHeight) / 2;
        }
        startX = 0;
        startY = 0;
        switch (mShapeType) {
            case 0:
                drawRectangle(canvas);
                break;
            case 1:
                drawCircle(canvas);
                break;
            case 2:
                drawSquare(canvas);
                break;
            default:
                break;
        }
    }

    private void drawSquare(Canvas canvas) {
        canvas.translate(translateX, translateY);
        if (progressList.size() > 0) {
            for (ProgressBean pro : progressList) {
                if (pro.isDefault()) {
                    paint.setColor(proBackColor);
                } else {
                    paint.setColor(progressSegmentColor);
                }
                if (pro.getProgress() == 0) {
                    canvas.drawCircle(startX, mHeight / 2, mHeight / 2, paint);
                }
                if (pro.getProgress() == 100) {
                    canvas.drawCircle(mWidth, mHeight / 2, mHeight / 2, paint);
                }
            }
        }
        paint.setColor(proBackColor);
        squareRectf.modify(startX, startY, mWidth, mHeight);
        canvas.drawRoundRect(squareRectf, squareRadius, squareRadius, paint);
        paint.setColor(proColor);
        if (progressList.size() > 0) {
            for (ProgressBean pro : progressList) {
                if (pro.isDefault()) {
                    paint.setColor(proBackColor);
                } else {
                    paint.setColor(progressSegmentColor);
                }
                squareRectf.modify(startX, startY, ((float) pro.getProgress() / max) * mWidth, mHeight);
                canvas.drawRoundRect(squareRectf, squareRadius, squareRadius, paint);
                startX = ((float) pro.getProgress() / max) * mWidth;
            }
        } else {
            squareRectf.modify(startX, startY, ((float) progress / max) * mWidth, mHeight);
            canvas.drawRoundRect(squareRectf, squareRadius, squareRadius, paint);
        }
        drawText(canvas);
    }

    private void drawText(Canvas canvas) {
        if (showText) {
            if (progress < (max / 3)) {
                paint.setColor(textLowColor);
            } else if (progress < (max / 3) * 2 && progress > (max / 3)) {
                paint.setColor(textMiddleColor);
            } else {
                paint.setColor(textHighColor);
            }
            canvas.drawText(paint, progress + "%", ((float) progress / max) * mWidth - (progress == 0 ? 0 :
                            textSize),
                    mHeight + textSize);
        }
    }

    private void drawCircle(Canvas canvas) {
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setColor(proColor);
        circleRectf.modify(circleX, circleX, circleX + circleR * 2, circleX + circleR * 2);
        if (progressList.size() > 0) {
            startR = -90;
            float last = 0;
            boolean isOu = true;
            for (ProgressBean pro : progressList) {
                Arc arc = new Arc();
                arc.setArc(startR, ((pro.getProgress() - last) / max) * 360, false);
                canvas.drawArc(circleRectf, arc, paint);
                startR = ((pro.getProgress() - last) / max) * 360 + startR;
                last = pro.getProgress();
                if (isOu) {
                    paint.setColor(progressSegmentColor);
                } else {
                    paint.setColor(proColor);
                }
                isOu = !isOu;
            }
        } else {
            Arc arc = new Arc();
            arc.setArc(startR, ((float) progress / max) * 360, false);
            canvas.drawArc(circleRectf, arc, paint);
        }
        if (showText) {
            paint.reset();
            paint.setStrokeWidth(1);
            paint.setTextSize((int) textSize);
            if (progress < (max / 3)) {
                paint.setColor(textLowColor);
            } else if (progress < (max / 3) * 2 && progress > (max / 3)) {
                paint.setColor(textMiddleColor);
            } else {
                paint.setColor(textHighColor);
            }
            if (progress == max) {
                canvas.drawText(paint, "done", circleX + textSize / 2f, circleX + textSize * 2f);
            } else {
                canvas.drawText(paint, progress + "%", circleX + textSize / 2f, circleX + textSize * 2f);
            }
        }
    }

    private void drawRectangle(Canvas canvas) {
        canvas.drawRect(startX, startY, mWidth, mHeight, paint);
        paint.setColor(proColor);
        if (progressList.size() > 0) {
            for (ProgressBean pro : progressList) {
                if (pro.isDefault()) {
                    paint.setColor(proBackColor);
                } else {
                    paint.setColor(progressSegmentColor);
                }
                canvas.drawRect(startX, startY, ((float) pro.getProgress() / max) * mWidth,
                        mHeight, paint);
                startX = ((float) pro.getProgress() / max) * mWidth;
            }
        } else {
            canvas.drawRect(startX, startY, ((float) progress / max) * mWidth,
                    mHeight, paint);
        }
        drawText(canvas);
    }


    // - - - - - - - - - - - - -  public - - - - - - - - - - - - - - - - -


    public int getProgress() {
        return progress;
    }

    /**
     * 设置分段显示进度条的某个进度
     *
     * @param progress 进度
     * @param isDefaul 是否为默认背景色
     */
    public void setProgress(int progress, boolean isDefaul) {
        if (progress <= max) {
            ProgressBean bean = progressList.get(progress);
            bean.setProgress(progress);
            bean.setDefault(isDefaul);
            progressList.set(progress, bean);
            invalidate();
        }
    }

    public void setProgressList(List<ProgressBean> list) {
        if (list == null || list.isEmpty()) {
            return;
        }
        progressList.clear();
        progressList.addAll(list);
        invalidate();
    }

    /**
     * 清除某个进度
     *
     * @param progres 进度
     */
    public void removeProgress(int progres) {
        if (progressList.size() > 0) {
            progressList.remove(progressList.size() - 1);
            if (progressList.size() == 0) {
                progress = DEFAULT_PROGRESS;
            } else {
                progress = progressList.get(progressList.size() - 1).getProgress();
            }
        } else {
            progress = progres;
        }
        invalidate();
    }


}
